package com.core.framework.tools.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.core.framework.tools.Tools;
/**
 * Bean 反射帮助类
 * @author 刘涛
 * @since Jun 27, 2012
 */
public class BeanReflectUtil {

	public static void main(String[] args) {
	}

	public static Method getMethod(Class<?> clazz, String name) {
		for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				if (!superClass.getName().contains("EnhancerBySpring"))
					return superClass.getDeclaredMethod(name);
			} catch (Exception e) {
				// Field不在当前类定义,继续向上转型
			}
		}
		return null;
	}

	static public void setValue(Object obj, String propertyName, Object value) {
		try {
			org.apache.commons.beanutils.BeanUtils.setProperty(obj,
					propertyName, value);
		} catch (IllegalAccessException e) {

			e.printStackTrace();
		} catch (InvocationTargetException e) {

			e.printStackTrace();
		}
	}

	static public Object getPropertyValue(Object obj, String propertyName) {
		try {
			return org.apache.commons.beanutils.BeanUtils.getProperty(obj,
					propertyName);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * <p>
	 * Description:[把Bean对象的属性和值映射成一个MAP]
	 * </p>
	 * <p>
	 * Created by [Huyvanpull] [Jul 6, 2009]
	 * </p>
	 * <p>
	 * Midified by [修改人] [修改时间]
	 * </p>
	 * 
	 * @return
	 */
	public static Map<String, Object> bean2Map(Object bean) {
		Map<String, Object> fieldNVMap = new HashMap<String, Object>();
		/** */
		/** 如果bean参数的值为null,直接返回 */
		if (bean == null) {
			return fieldNVMap;
		}
		Class<?> claz = bean.getClass();
		/** */
		/** 得到bean的所有成员变量 */
		Field[] fileds = claz.getDeclaredFields();
		for (Field field : fileds) {
			String fieldName = field.getName();
			String getterMethodName = getGetterOrSetterName(fieldName, "get");
			Object filedValue = null;
			try {
				/** */
				/** 根据成员变量得到该变量的Getter方法 */
				Method method = claz.getMethod(getterMethodName);
				if (method != null) {
					/** */
					/** 根据该成员变量的Getter方法得到该方法的值 */
					filedValue = method.invoke(bean, new Object[0]);
				}
				fieldNVMap.put(fieldName, filedValue);
			} catch (Exception ex) {
			}
		}
		return fieldNVMap;
	}

	/**
	 * 
	 * <p>
	 * Description:[根据成员变量名,得到成员变量的Getter或Setter方法名]
	 * </p>
	 * <p>
	 * Created by [Huyvanpull] [Jul 6, 2009]
	 * </p>
	 * <p>
	 * Midified by [修改人] [修改时间]
	 * </p>
	 * 
	 * @param fieldName
	 * @return
	 */
	static private String getGetterOrSetterName(String fieldName, String prdfix) {
		StringBuffer getterOrSetterName = new StringBuffer();
		getterOrSetterName.append(prdfix);
		getterOrSetterName.append(fieldName.substring(0, 1).toUpperCase());
		if (getterOrSetterName.length() > 1) {
			getterOrSetterName.append(fieldName.substring(1));
		}
		return getterOrSetterName.toString();
	}

	private static Logger logger = Logger.getLogger(BeanReflectUtil.class);

	public static Object getBeanPropertyValue(Object o, String columnName) {
		return invokeMethod(o, Tools.toGetOntRowName(columnName));
	}

	/**
	 * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
	 */
	public static Object getFieldValue(final Object object,
			final String fieldName) {
		try {
			Field field = getDeclaredField(object, fieldName);
			if (field == null)
				throw new IllegalArgumentException("Could not find field ["
						+ fieldName + "] on target [" + object + "]");
			makeAccessible(field);
			Object result = null;

			result = field.get(object);
			return result;
		} catch (Exception e) {

		}
		return null;
	}

	/**
	 * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
	 */
	public static void setFieldValue(final Object object,
			final String fieldName, final Object value) {

		try {
			Field field = getDeclaredField(object, fieldName);
			makeAccessible(field);
			if (field == null) {
				return;
			}
			field.set(object, value);
		} catch (Exception e) {

		}
	}

	/**
	 * 直接调用对象方法, 无视private/protected修饰符.
	 */
	public static Object invokeMethod(final Object object,
			final String methodName, final Class<?>[] parameterTypes,
			final Object[] parameters) {
		Method method = getDeclaredMethod(object, methodName, parameterTypes);
		if (method == null)
			throw new IllegalArgumentException("Could not find method ["
					+ methodName + "] on target [" + object + "]");
		method.setAccessible(true);
		try {
			return method.invoke(object, parameters);
		} catch (Exception e) {
			throw convertReflectionExceptionToUnchecked(e);
		}
	}

	public static Object invokeMethod(final Object object,
			final String methodName) {
		Method method = getDeclaredMethod(object, methodName);
		if (method == null)
			throw new IllegalArgumentException("Could not find method ["
					+ methodName + "] on target [" + object + "]");
		method.setAccessible(true);
		try {
			return method.invoke(object);
		} catch (Exception e) {
			throw convertReflectionExceptionToUnchecked(e);
		}
	}

	/**
	 * 循环向上转型, 获取对象的DeclaredField.
	 * 
	 * 如向上转型到Object仍无法找到, 返回null.
	 */
	protected static Field getDeclaredField(final Object object,
			final String fieldName) {

		for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				return superClass.getDeclaredField(fieldName);
			} catch (NoSuchFieldException e) {
				// Field不在当前类定义,继续向上转型
			}
		}
		return null;
	}

	/**
	 * 强行设置Field可访问.
	 */
	protected static void makeAccessible(final Field field) {
		if (!Modifier.isPublic(field.getModifiers())
				|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
			field.setAccessible(true);
		}
	}

	/**
	 * 循环向上转型,获取对象的DeclaredMethod.
	 * 
	 * 如向上转型到Object仍无法找到, 返回null.
	 */
	protected static Method getDeclaredMethod(Object object, String methodName,
			Class<?>... parameterTypes) {

		for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				return superClass.getDeclaredMethod(methodName, parameterTypes);
			} catch (NoSuchMethodException e) {
				// Method不在当前类定义,继续向上转型
			}
		}
		return null;
	}

	protected static Method getDeclaredMethod(Object object, String methodName) {

		for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				return superClass.getDeclaredMethod(methodName);
			} catch (NoSuchMethodException e) {
				// Method不在当前类定义,继续向上转型
			}
		}
		return null;
	}

	/**
	 * 通过反射,获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class. eg. public UserDao
	 * extends HibernateDao<User>
	 * 
	 * @param clazz
	 *            The class to introspect
	 * @return the first generic declaration, or Object.class if cannot be
	 *         determined
	 */
	@SuppressWarnings("unchecked")
	public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
		return getSuperClassGenricType(clazz, 0);
	}

	/**
	 * 通过反射,获得定义Class时声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
	 * 
	 * 如public UserDao extends HibernateDao<User,Long>
	 * 
	 * @param clazz
	 *            clazz The class to introspect
	 * @param index
	 *            the Index of the generic ddeclaration,start from 0.
	 * @return the index generic declaration, or Object.class if cannot be
	 *         determined
	 */
	@SuppressWarnings("unchecked")
	public static Class getSuperClassGenricType(final Class clazz,
			final int index) {
		Type genType = clazz.getGenericSuperclass();
		if (!(genType instanceof ParameterizedType)) {
			logger.warn(clazz.getSimpleName()
					+ "'s superclass not ParameterizedType");
			return Object.class;
		}
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		if (index >= params.length || index < 0) {
			logger.warn("Index: " + index + ", Size of "
					+ clazz.getSimpleName() + "'s Parameterized Type: "
					+ params.length);
			return Object.class;
		}
		if (!(params[index] instanceof Class)) {
			logger
					.warn(clazz.getSimpleName()
							+ " not set the actual class on superclass generic parameter");
			return Object.class;
		}
		return (Class) params[index];
	}

	/**
	 * 将反射时的checked exception转换为unchecked exception.
	 */
	public static RuntimeException convertReflectionExceptionToUnchecked(
			Exception e) {
		if (e instanceof IllegalAccessException
				|| e instanceof IllegalArgumentException
				|| e instanceof NoSuchMethodException
				|| e instanceof InvocationTargetException)
			return new IllegalArgumentException("Reflection Exception.", e);
		else
			return new RuntimeException(e);
	}

	public static Object convertValue(String value, Class<?> propertyType) {
		// 
		return value;
	}
}
